#ifndef __UNIQUE_ONLY__

#define __UNIQUE_ONLY__ 

#endif

#include<iostream>
#include<stdarg.h>
#include<stdio.h>
#include<string>
#include<time.h>
#include<vector>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>


enum grade
{
  Info,      //常规 0
  Warning,   //警告 1
  Error,     //错误 2
  Fatal,     //致命 3
  Debug      //调试 4
};

//日志 等级 + 时间 + 行号 + 内容
class log
{
public:
  log(size_t flag = 0)
    :_flag(flag)
  {}


  void operator()(size_t grade, int line, const char* s, ...)
  {
    std::string ans; 
    //等级
    std::string s1 = getGrade(grade);
    
    //时间
    time_t t = time(nullptr);
    struct tm* m = localtime(&t);

    char s2[1024] = {'\0'};
    snprintf(s2, 1024, "[%s][time: %d - %d - %d %d:%d:%d][Line numbre: %d]", s1.c_str(), m->tm_year + 1900, m->tm_mon + 1, m->tm_mday, m->tm_hour, m->tm_min, m->tm_sec, line);

    //内容
    va_list s3;
    va_start(s3, s);
    char s4[1024] = {'\0'};
    vsnprintf(s4, 1024, s, s3);

    //拼接
    ans += s2;
    ans += "[content: "; 
    ans += s4; 
    ans += "]";
    ans += "\n";
    _log.push_back(ans);
  }

  //输出日志文件
  
  ~log()
  {
    switch(_flag)
    {
      case 0:
        for (auto s : _log)
        {
           std::cout << s << std::endl;
        }
        outputClassfile(); 
        break;
      case 1:
        for (auto s : _log)
        {
           std::cout << s << std::endl;
        }
        break;
      case 2:
        for (auto s : _log)
        {
           std::cout << s << std::endl;
        }
        outputOnefile();
        break;
      case 3:
        outputOnefile();
        break;
      case 4:
        outputClassfile();
        break;
      default:
        operator()(Error, 98, "flag set error");
        for (auto s : _log)
        {
           std::cout << s << std::endl;
        }
      break;
    }
  }

private:
  bool outputOnefile()
  {
    int fd = open("./log.log",O_CREAT | O_WRONLY | O_APPEND, 0666);
    if (fd == -1)
    {
      operator()(Error, 113, "uotputOnefile create file lose");
      return false;
    }

    for (auto s : _log)
    {
      int c = write(fd, s.c_str(), s.size());
      if (c == -1)
      {
        operator()(Error, 122, "write file lose");
        return false;
      }
    }
    return true;
  }

  bool outputClassfile()
  {
    mkdir("./log", 0777);

    std::vector<int> fd(6);
    for (int i = 0; i <= 5; i++)
    {
      std::string s = "./log/"; 
      s += "log_" + getGrade(i);
      s += ".log";
      int c = open(s.c_str(),O_CREAT | O_WRONLY | O_APPEND, 0666);
      if (c == -1)
      {
        operator()(Error, 142, "uotputClassfile create file lose");
        return false;
      }
      fd[i] = c;
    }

    for (auto s : _log)
    {
      int end = s.find("]");
      std::string t = s.substr(1, end - 1);

      int c = write(fd[Grade(t)], s.c_str(), s.size());
      if (c == -1)
      {
        operator()(Error, 156, "write file lose");
        return false;
      }
    }

    return true;
  }

  int Grade(std::string& g)
  {
    if (g == "Info")
    {
      return 0;
    }
    else if (g == "Warning")
    {
      return 1;
    }
    else if (g == "Error")
    {
      return 2;
    }
    else if (g == "Fatal")
    {
      return 3;
    }
    else if (g == "Debug")
    {
      return 4;
    }

    return 5;
  }


  static std::string getGrade(size_t g)
  {
    switch (g)
    {
      case Info:
        return "Info";
        break;  
      case Warning:
        return "Warning";
        break;
      case Error:
        return "Error";
        break;
      case Fatal:
        return "Fatal";
        break;
        case Debug:
        return "Debug";
        break;
      default:
        return "None";
        break;
    }
  }
  
  //0 默认  1 只打印  2 打印并存储在一个文件  默认 打印并分类存文件 3 不打印，只写同一个文件 4 不打印，分类写
  size_t _flag;
  //暂时存储日志
  std::vector<std::string> _log;
};
